/* eslint-disable react/jsx-handler-names */
/* eslint-disable eqeqeq */
/* eslint-disable react/no-did-mount-set-state */
/* eslint-disable react/no-unused-state */
/**
 * 产品+组合 业务组件 树形结构
 * by zhangxinyue
 * create 2021-07-29
 */
import React from 'react';
import { connect } from 'dva';
import PropTypes from 'prop-types';
import { TreeSelect, Tooltip } from 'antd';
import _ from 'lodash';
import debounce from 'lodash/debounce';

class ProductGroupTreeCom extends React.PureComponent {
  // props默认值
  static defaultProps = {
    placeholder: '请选择组合',
    onChange: () => {},
    onRef: () => {}, // 本组件的引用
    width: '100%',
    maxTagCount: 0,
    productId: undefined, // 默认无产品ID，获取所有产品下的组合
    ralation: false, // 默认单独展示，无关联关系
    rules: undefined, // 默认无校验规则
    multiple: true, // 默认支持多选
    allowClear: true, // 默认可删除
    authority: 'read', // 默认是读权限
    disabled: false, // 默认不禁用
    treeCheckable: false, // 默认不显示
    maatApi: false, // 默认什么环境下就用什么该环境的组合
    toolTipPlace: undefined, // tooltip显示位置(默认多选时展示在右边，单选时展示在上面)
    productGroup: [],
    initChangeFlag: false, // init时抛出onchange事件
  };

  constructor(props) {
    super(props);
    this.state = {
      groupDS: undefined, // 与产品有关联关系的数据源
      dataSource: undefined,
      treeExpandedKeys: [], // 记录树展开的节点（解决数据刷新时，树节点未默认展开问题）
      tooltipInfo: '', // 提示信息
      tooltips: null, // 存放tooltip的值
      countBlur: 0,
      isClearAll: false, // 是否删除了所有项目
      searchValue: '',
      toolTipValue: '', // 产品组合联动 将回填的value值缓存 用于设置tooltip
    };
    this.childrenNode = [];
  }

  componentDidMount() {
    // 父组件对本组件的引用
    this.props.onRef(this);
    if (this.props.productCode) {
      // 如果是通过产品code查询组合列表，展示单个组合，负债端维护页面，请求对应接口得到productAGroupM.productGroup
      if (this.props.productAGroupM.productGroupFuZhai) {
        const keys = [];
        this.findParentKey(this.state.dataSource, keys);
        this.setState({
          treeExpandedKeys: keys,
          dataSource: this.props.productAGroupM.productGroupFuZhai,
        });
      }
      return;
    }
    // 获取组合的全量数据(联动不获取，都获取全量数据，方便onChange和tooltip获取信息)
    if (!this.props.ralation)
      this.getProductGroup(undefined, this.props.authority, (dataSource) => {
        // console.log('初始化请求全量数据');
        if (!this.initData) {
          this.initData = _.cloneDeep(dataSource);
        }
        if (!this.props.ralation && dataSource) {
          // console.log('拿到数据之后已经对dataSource赋值，就不用考虑props的变量变化,否则会出现互相干扰数据');
          const keys = [];
          this.findParentKey(dataSource, keys);
          this.setState({
            treeExpandedKeys: keys,
            dataSource,
          });
        }

        // 若有同步的初始化数据，则设置tooltip
        if (this.props.initialValue) {
          this.setTooltip(this.props.initialValue, this.props);
        }
      });
    // 联动时，有产品ID时，调用接口，获取产品下的组合
    if (this.props.ralation && this.props.productId) {
      // 有同步初始化值，则设置对应的tooltip
      if (this.props.initialValue) {
        this.initSeletData(this.props.productId, this.props.authority, true, this.props.initialValue);
      } else {
        this.initSeletData(this.props.productId, this.props.authority);
      }
    }
    // 联动同步无初始化添加提示
    if (this.props.ralation && !this.props.productId) {
      this.initDataG = [{ value: 'blank', title: '请先选择产品', disabled: true }];
      this.setState({
        groupDS: [{ value: 'blank', title: '请先选择产品', disabled: true }],
      });
    }
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.initialValue != prevState.initialValue) {
      // 用于异步初始化 初始值的 比对
      return {
        ...prevState,
        initialValue: nextProps.initialValue,
      };
    } else {
      return null;
    }
  }

  // eslint-disable-next-line max-statements
  componentDidUpdate(preProps) {
    const { props } = this;
    const initValue = preProps.initialValue ? JSON.stringify(preProps.initialValue) : '';
    const initValueN = this.state.initialValue ? JSON.stringify(this.state.initialValue) : '';
    if (this.props.ralation) {
      // 产品与组合联动
      // 判断产品是否渲染完成
      if (props.dataIndex0 != undefined) {
        const value0 = props.form?.getFieldValue(props.dataIndex0);
        if (value0 == undefined) {
          // 处理当重置时，清空下拉数据
          this.props.resetChange(undefined);
        }
      }
      if (preProps.productId != props.productId) {
        // 清空tooltip
        this.setState({
          tooltipInfo: '',
        });
        // 因formItem与表单组件之间不可以有div，所以这里抛给父组件
        this.props.onChangeTip && this.props.onChangeTip('');
        // productId==undefined，证明未选中任何产品，组合下拉内容置空
        if (props.productId === undefined) {
          this.initDataG = [{ value: 'blank', title: '请先选择产品', disabled: true }];
          this.setState({
            groupDS: [{ value: 'blank', title: '请先选择产品', disabled: true }],
          });
        } else {
          // 若外部传了产品ID，则先把老的数据清除，再调用接口，根据产品ID，获取其下组合数据
          this.setState({
            groupDS: undefined,
          });
          this.initSeletData(props.productId, props.authority);
        }
      }
    } else {
      // 单组合，不与产品联动
      let ds, dsN;
      if (this.props.productCode) {
        // 负债端维护
        ds = preProps.productAGroupM.productGroupFuZhai ? JSON.stringify(preProps.productAGroupM.productGroupFuZhai) : '';
        dsN = props.productAGroupM.productGroupFuZhai ? JSON.stringify(props.productAGroupM.productGroupFuZhai) : '';
        if (this.state.dataSource) {
          const keys = [];
          this.findParentKey(props.productAGroupM.productGroupFuZhai, keys);
          this.setState({
            treeExpandedKeys: keys,
            dataSource: props.productAGroupM.productGroupFuZhai,
          });
        }
      } else {
        ds = preProps.productAGroupM.productGroup ? JSON.stringify(preProps.productAGroupM.productGroup) : '';
        dsN = props.productAGroupM.productGroup ? JSON.stringify(props.productAGroupM.productGroup) : '';
      }
      // 初始化值或全量数据变更时，设置tooltip
      if (initValue != initValueN || (ds != dsN && this.props.investmentType)) {
        // console.log('初始化数据延迟');
        props.form.setFieldsValue({ [props.dataIndex]: props.initialValue });
      }
    }
  }

  // 非初始化状态下更改下拉选项(供父组件调用)
  setSelect = (value) => {
    const valueF = {};
    valueF[this.props.dataIndex] = value;
    this.props.form.setFieldsValue(valueF);
    if (this.props.ralation) {
      // 产品与组合联动时  外部设置值
      this.setState({
        toolTipValue: value,
      });
      return;
    }
    this.setTooltip(value);
  };

  // 获取onchange应该对外抛出的内容（供父组件调用）
  setOnChangeInfo = (e) => {
    const args = { key: e, info: undefined };
    // let ds = this.props.ralation ? this.state.groupDS : this.state.dataSource;
    let ds;
    if (this.props.ralation) {
      // console.log(this.state.groupDS,'&&&&')
      // 产品+组合组件 如果初始化时没数据，groupD是加载中的提示，这个时候比对的是全量数据
      ds = this.state.groupDS?.length && this.state.groupDS[0].value == 'blank' ? this.state.dataSource : this.state.groupDS || this.state.dataSource;
    } else {
      ds = this.state.dataSource;
    }
    if (e && !ds) ds = this.initData; // setselect外部调用修改值时  {key ，info}抛出的数据 info为undefined
    // 多选
    if (this.props.multiple) {
      const info = [];
      e.forEach((element) => {
        const nodeInfo = [];
        this.findNode(ds, element, nodeInfo);
        info.push(nodeInfo[0]);
      });
      args.info = info;
    } else {
      // 单选
      const nodeInfo = [];
      this.findNode(ds, e, nodeInfo);
      args.info = nodeInfo[0];
    }
    return args;
  };

  // 遍历树形结构，找出所有非叶子节点
  findParentKey = (data, keys) => {
    if (data && data.length > 0) {
      data.forEach((item) => {
        if (item && item.children && item.children.length > 0) {
          keys.push(item.key);
          this.findParentKey(item.children, keys);
        }
      });
    }
  };

  // 初始化下拉数据
  // productId-产品ID
  // authority-权限
  // setTooltip- 是否需要设置tooltip
  // value-若需要设置tooltip，那么对应的值是什么
  initSeletData = (productId, authority, setTooltip = false, value = undefined) => {
    // value是组合的默认值，如果没有默认值就是undefined  如果有默认值
    // args是获取的数据
    // 调用接口，获取产品下的组合数据
    this.getProductGroup(productId, authority, (args) => {
      this.initDataG = _.cloneDeep(args);
      this.setState({
        groupDS: args,
      });
      // 找出所有父节点，并展开
      const keys = [];
      this.findParentKey(args, keys);
      this.setState({
        treeExpandedKeys: keys,
      });
      if (this.state.toolTipValue) {
        // setselect 时  设置tooltip

        const tempVal = this.state.toolTipValue;
        this.setState({
          toolTipValue: '',
        });
        this.setTooltip(tempVal);

        if (this.props.initChangeFlag) {
          // 抛出初始化的 事件
          this.props.onChange(tempVal);
        }
      }

      // 设置tooltip
      if (setTooltip) {
        this.setTooltip(value);
        if (this.props.initChangeFlag) {
          // 抛出初始化的 事件
          this.props.onChange(value);
        }
      }
    });
  };

  // 根据节点value,找到节点
  findNode = (data, key, node) => {
    if (data && data.length > 0) {
      data.forEach((item) => {
        if (item && item.value == key) {
          node.push(item);
        } else if (item && item.children && item.children.length > 0) {
          this.findNode(item.children, key, node);
        }
      });
    }
  };

  // 设置tooltip
  setTooltip = (e, propT = this.props) => {
    let ds;
    if (propT.ralation) {
      // 产品+组合组件 如果初始化时没数据，groupD是加载中的提示，这个时候比对的是全量数据
      ds = this.state.groupDS?.length && this.state.groupDS[0].value == 'blank' ? this.initData : this.state.groupDS || this.initData;
    } else {
      ds = this.initData;
    }
    if (ds == undefined) {
      // 因formItem与表单组件之间不可以有div，所以这里抛给父组件
      this.props.onChangeTip && this.props.onChangeTip('');
      return;
    }
    const { multiple } = propT;
    let tooltipInfo = '';
    if (e != undefined && e != null) {
      if (Array.isArray(e) && multiple) {
        // 多选
        e.forEach((element, index) => {
          const nodeInfo = [];
          this.findNode(ds, element, nodeInfo);

          if (nodeInfo.length > 0) {
            tooltipInfo += nodeInfo[0].title;
          }
          // 最后一个元素之后不用换行
          if (index != e.length - 1) {
            tooltipInfo += '\r\n';
          }
        });
      } else {
        // 单选
        const nodeInfo = [];
        this.findNode(ds, e, nodeInfo);
        if (nodeInfo.length > 0) {
          tooltipInfo += nodeInfo[0].title;
        }
      }
    }
    this.setState(
      {
        tooltipInfo: tooltipInfo == '' ? '' : <div style={{ whiteSpace: 'pre' }}>{tooltipInfo}</div>,
      },
      () => {
        // 因formItem与表单组件之间不可以有div，所以这里抛给父组件
        this.props.onChangeTip && this.props.onChangeTip(this.state.tooltipInfo);
      },
    );
  };

  // 调用接口，获取产品+组合树形结构
  getProductGroup = (productId, authority, callback) => {
    const { investmentType } = this.props;
    // 当设置了产品ID时，获取产品下的组合
    if (productId) {
      this.props.dispatch({
        type: 'productAGroupM/getProductGroup',
        payload: {
          rootId: productId,
          authority,
          maatApi: this.props.maatApi,
          inveType: this.props.inveType,
          tradeModel: this.props.tradeModel,
        },
        callback,
      });
    } else {
      // 当未设置产品ID时，获取全量信息
      const params = {
        authority,
        maatApi: this.props.maatApi,
        inveType: this.props.inveType,
        tradeModel: this.props.tradeModel,
      };
      if (investmentType) {
        params.investmentType = investmentType;
        this.props.dispatch({
          type: 'productAGroupM/getProductGroup',
          payload: {
            ...params,
          },
          callback: (res) => {
            const keys = [];
            this.findParentKey(res, keys);
            // let newDataSource = res.slice(0, 300)

            if (!this.initData) {
              this.initData = _.cloneDeep(res);
            }
            // 拿到数据之后已经对dataSource赋值，就不用考虑props的变量变化
            this.setState({
              dataSource: res,
              treeExpandedKeys: keys,
            });
            // 若有同步的初始化数据，则设置tooltip
            if (this.props.initialValue) {
              this.setTooltip(this.props.initialValue, this.props);
            }
          },
        });
        return;
      }
      this.props.dispatch({
        type: 'productAGroupM/getProductGroup',
        payload: {
          ...params,
        },
        callback,
      });
    }
  };

  // 树节点展开事件，解决数据刷新时，树节点未默认展开问题
  onTreeExpand = (expandedKeys) => {
    this.setState({
      treeExpandedKeys: expandedKeys,
    });
  };

  // 选中树节点变更事件
  onChange = (e) => {
    // 此处需要注意当如果是有默认值的时候，但是直接删除的话，需要将所有的值开始重新截取
    this.props.onChange(e);
    this.setTooltip(e);
  };

  render() {
    const { styleRow, value, initialValue, placeholder, maxTagCount, width, ralation, multiple, allowClear, disabled, treeCheckable, toolTipPlace, positionBody, investmentType } =
      this.props;
    const { dataSource } = this.state;
    return (
      <TreeSelect
        getPopupContainer={(triggerNode) => (!positionBody ? triggerNode.parentNode : document.body)}
        value={value}
        style={styleRow ? styleRow : { width }}
        maxTagCount={maxTagCount}
        placeholder={placeholder} // 占位符
        onChange={this.onChange} // 选中树节点时调用此函数
        treeData={
          // 数据源
          ralation
            ? this.state.groupDS != undefined && Array.isArray(this.state?.groupDS)
              ? this.state.groupDS
              : [{ value: 'blank', title: '正在加载中...', disabled: true }]
            : Array.isArray(dataSource)
            ? dataSource
            : [{ value: 'blank', title: '正在加载中...', disabled: true }]
        }
        multiple={multiple} // 支持多选（当设置 treeCheckable 时自动变为 true）
        treeCheckable={treeCheckable} // 设置checkbox的显示或隐藏
        showCheckedStrategy={treeCheckable ? TreeSelect.SHOW_ALL : TreeSelect.SHOW_CHILD}
        allowClear={allowClear} // 显示清除按钮
        treeDefaultExpandAll={true} // 默认展开所有树节点（仅初始化时生效）
        treeExpandedKeys={ralation ? this.state.treeExpandedKeys : this.state.treeExpandedKeys} // 设置树节点展开
        onTreeExpand={ralation ? this.onTreeExpand : this.onTreeExpand} // 树节点展开调用事件
        dropdownMatchSelectWidth={true} // 下拉菜单和选择器同宽
        disabled={disabled}
        autoClearSearchValue={true} // 当多选模式下值被选择，不清空搜索框
        showSearch={true} // 支持模糊查询
        filterTreeNode={(inputVal, node) => node.title.includes(inputVal)} // 用组件自带的搜索 以title 进行模糊匹配
        treeNodeFilterProp='title'
        // defaultValue={initialValue}
        // onSearch={this.handleSearch}
        // searchValue={this.state.searchValue}
      />
    );
  }
}

// props类型
ProductGroupTreeCom.propsTypes = {
  form: PropTypes.object, // form对象
  title: PropTypes.string, // 显示名称
  dataIndex: PropTypes.string, // Form识别的Item ID
  initialValue: PropTypes.oneOfType([
    // 初始默认值
    PropTypes.string, // 单选模式
    PropTypes.array, // 多选模式
  ]),
  rules: PropTypes.object, // 校验规则
  placeholder: PropTypes.string, // 占位符
  onChange: PropTypes.func, // 输入框内容变化时的回调
  helper: PropTypes.oneOfType([
    // 提示帮助信息
    PropTypes.string,
    PropTypes.element,
  ]),
  onRef: PropTypes.func, // 本组件的引用（可用来父组件调用内部方法）
  maxTagCount: PropTypes.number,
  productId: PropTypes.string, // 产品ID（在ralation为true时，设置productId生效）
  ralation: PropTypes.bool, // 设置是否与产品有关联关系
  multiple: PropTypes.bool, // 是否支持多选
  allowClear: PropTypes.bool, // 设置是否可删除
  authority: PropTypes.oneOf(['read', 'write']), // 设置权限类型
  disabled: PropTypes.bool, // 是否禁用
  treeCheckable: PropTypes.bool, // 是否显示checkbox
  maatApi: PropTypes.bool, // 正常情况下，在哪个环境下，就访问哪个环境的组合，
  // 但在投资建议书模块中，被引用到资管环境时，该组件的接口仍然要访问maat环境中的组合（而不是资管环境中组合），此时需要在接口前添加maat前缀
  toolTipPlace: PropTypes.string, // tooltip显示位置(未设置时，默认多选时展示在右边，单选时展示在上面，设置了就按设置的位置展示)
  investmentType: PropTypes.string, // 筛选投资类型， FB ==>产品基本信息中，投资类型为非标类的产品
  initChangeFlag: PropTypes.bool, // 初次是否抛出onchange事件 默认false (首次在非标工作台添加交易中使用)
};

export default connect(({ productAGroupM, loading }) => ({ productAGroupM, loading }))(ProductGroupTreeCom);
